﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ROrganizer.UI.Controllers;
using ROrganizer.UI.Forms.Core;

namespace ROrganizer.UI.Forms
{
    internal partial class CommitForm : Form
    {
        private readonly CommitFormController controller;

        public CommitForm()
        {
            this.controller = new CommitFormController(this.ProcessException);
            this.InitializeComponent();

            this.olvChanges.Objects = controller.Changes;
            this.olvChanges.Sort(this.chTitle, SortOrder.Ascending);

            this.controller.Changed += this.OnChanged;
            this.controller.Changes.CollectionChanged += this.OnChanged;
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            this.olvChanges.Normalize();
            this.RefreshActions();
        }

        protected override void OnClosing(CancelEventArgs e)
        {
            e.Cancel = this.controller.IsWorking;
            base.OnClosing(e);
        }

        private void OnChanged(object sender, EventArgs e)
        {
            if (this.SynchronizeInvocation(this.OnChanged, sender, e))
            {
                this.pbMain.Value = Math.Min(this.pbMain.Maximum, this.controller.Progress);
                this.RefreshActions();
            }
        }

        private void OnChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (e.Action == NotifyCollectionChangedAction.Reset)
                this.olvChanges.ClearObjects();

            if (e.OldItems != null)
                this.olvChanges.RemoveObjects(e.OldItems);

            if (e.NewItems != null)
                this.olvChanges.AddObjects(e.NewItems);
        }

        private void OnCommit(object sender, EventArgs e)
        {
            this.ExecuteAndWatch(this.Commit);
        }

        private void Commit()
        {
            this.controller.Commit(this);
            this.RefreshActions();
        }

        private void OnCommitSelected(object sender, EventArgs e)
        {
            this.ExecuteAndWatch(this.CommitSelected);
        }

        private void CommitSelected()
        {
            this.controller.Commit(this, changes: this.GetSelectedChanges());
            this.RefreshActions();
        }

        private void OnSelectionChanged(object sender, EventArgs e)
        {
            this.RefreshActions();
        }

        private void RefreshActions()
        {
            this.tsmiCommit.Enabled = this.controller.CanCommit(changes: this.GetSelectedChanges());
            this.btnCommit.Enabled = this.controller.CanCommit();
            this.btnCancel.Enabled = this.controller.CanCancel();
            this.pbMain.Visible = this.controller.IsWorking;
        }

        private CommitFormController.Change[] GetSelectedChanges()
        {
            return this.olvChanges.SelectedObjects.OfType<CommitFormController.Change>().ToArray();
        }
    }
}
